/*!
\copyright  Copyright (c) 2022-2023 Qualcomm Technologies International, Ltd.
            All Rights Reserved.
            Qualcomm Technologies International, Ltd. Confidential and Proprietary.
\file
\brief    Table and interface function used LE Audio Client Config
*/

#include "le_audio_client_audio_config.h"
#include <le_audio_client_broadcast_private.h>
#include "logging.h"
#include "kymera.h"
#include <panic.h>

#ifdef INCLUDE_LE_AUDIO_BROADCAST_SOURCE

/*! Presentation delay for broadcast */
#define LE_AUDIO_CLIENT_BROADCAST_PRESENTATION_DELAY        0x4E20

/*! LC3 blocks per SDU for broadcast */
#define LE_AUDIO_CLIENT_BROADCAST_LC3_BLOCKS_PER_SDU        1

/*! Number of subgroups for broadcast */
#define LE_AUDIO_CLIENT_BROADCAST_NUM_SUB_GROUPS            1

/*! Number of BIS for high quality configuration */
#define LE_AUDIO_CLIENT_BROADCAST_HIGH_QUALITY_NUM_BIS      2

/*! Structure to hold broadcast audio configuration */
le_audio_client_audio_broadcast_config_t lea_client_bcast_config;

#endif /* INCLUDE_LE_AUDIO_BROADCAST_SOURCE */

#ifdef INCLUDE_LE_AUDIO_UNICAST_SOURCE

/*! As per QBCE Spec(section 5.7.97), the PHY for Q2Q should be 0x80 */
#define LE_AUDIO_CLIENT_Q2Q_PHY                   (0x80)

/*! Use unframed for framing type */
#define LE_AUDIO_CLIENT_UNFRAMED                  (0x0)

/*! RTN from Central to Peripheral value for Gaming without VBC */
#define LE_AUDIO_CLIENT_RTN_GAME_NO_VBC_C_TO_P    (0x5)

/*! RTN from Central to Peripheral value for Gaming with VBC */
#define LE_AUDIO_CLIENT_RTN_GAME_WITH_VBC_C_TO_P  (0x3)

/*! RTN from Peripheral to Central value for Gaming with VBC */
#define LE_AUDIO_CLIENT_RTN_GAME_WITH_VBC_P_TO_C  (0x3)

/*! RTN from Central to Peripheral value for Gaming without VBC */
#define LE_AUDIO_CLIENT_APTX_LITE_RTN_GAME_NO_VBC_C_TO_P    (0x3)

/*! RTN from Central to Peripheral value for Gaming with VBC */
#define LE_AUDIO_CLIENT_APTX_LITE_RTN_GAME_WITH_VBC_C_TO_P  (0x3)

/*! RTN from Peripheral to Central value for Gaming with VBC */
#define LE_AUDIO_CLIENT_APTX_LITE_RTN_GAME_WITH_VBC_P_TO_C  (0x7)

/*! Audio Config for gaming */
le_audio_client_audio_config_t  le_audio_client_audio_config_gaming =
{
    .target_latency             = CAP_CLIENT_TARGET_LOWER_LATENCY,
    .sink_stream_capability     = CAP_CLIENT_STREAM_CAPABILITY_48_1,
    .source_stream_capability   = CAP_CLIENT_STREAM_CAPABILITY_UNKNOWN,
    .framing                    = LE_AUDIO_CLIENT_UNFRAMED,
    .phy_ctop                   = LE_AUDIO_CLIENT_Q2Q_PHY,
    .phy_ptoc                   = LE_AUDIO_CLIENT_Q2Q_PHY,
    .rtn_ctop                   = LE_AUDIO_CLIENT_RTN_GAME_NO_VBC_C_TO_P,
    .rtn_ptoc                   = 0x0
};

/*! Audio Config for gaming with VBC */
le_audio_client_audio_config_t  le_audio_client_audio_config_gaming_with_vbc =
{
    .target_latency             = CAP_CLIENT_TARGET_LOWER_LATENCY,
    .sink_stream_capability     = CAP_CLIENT_STREAM_CAPABILITY_48_1,
    .source_stream_capability   = CAP_CLIENT_STREAM_CAPABILITY_16_1,
    .framing                    = LE_AUDIO_CLIENT_UNFRAMED,
    .phy_ctop                   = LE_AUDIO_CLIENT_Q2Q_PHY,
    .phy_ptoc                   = LE_AUDIO_CLIENT_Q2Q_PHY,
    .rtn_ctop                   = LE_AUDIO_CLIENT_RTN_GAME_WITH_VBC_C_TO_P,
    .rtn_ptoc                   = LE_AUDIO_CLIENT_RTN_GAME_WITH_VBC_P_TO_C
};

/*! Audio Config for media usecase */
le_audio_client_audio_config_t  le_audio_client_audio_config_media =
{
    .target_latency             = CAP_CLIENT_TARGET_HIGH_RELIABILITY,
    .sink_stream_capability     = CAP_CLIENT_STREAM_CAPABILITY_48_2,
    .source_stream_capability   = CAP_CLIENT_STREAM_CAPABILITY_UNKNOWN,
    .framing                    = LE_AUDIO_CLIENT_UNFRAMED,
    .phy_ctop                   = LE_AUDIO_CLIENT_Q2Q_PHY,
    .phy_ptoc                   = LE_AUDIO_CLIENT_Q2Q_PHY,
    .rtn_ctop                   = LE_AUDIO_CLIENT_RTN_GAME_NO_VBC_C_TO_P,
    .rtn_ptoc                   = 0x0
};

/*! Audio Config for conversational usecase */
le_audio_client_audio_config_t  le_audio_client_audio_config_conversational =
{
    .target_latency             = CAP_CLIENT_TARGET_BALANCE_LATENCY_AND_RELIABILITY,
    .sink_stream_capability     = TMAP_CLIENT_STREAM_CAPABILITY_32_2,
    .source_stream_capability   = TMAP_CLIENT_STREAM_CAPABILITY_32_2,
    .framing                    = LE_AUDIO_CLIENT_UNFRAMED,
    .phy_ctop                   = LE_AUDIO_CLIENT_Q2Q_PHY,
    .phy_ptoc                   = LE_AUDIO_CLIENT_Q2Q_PHY,
    .rtn_ctop                   = LE_AUDIO_CLIENT_RTN_GAME_WITH_VBC_C_TO_P,
    .rtn_ptoc                   = LE_AUDIO_CLIENT_RTN_GAME_WITH_VBC_P_TO_C
};

#ifdef INCLUDE_LE_AUDIO_GAMING_MODE_APTX_LITE
/*! Audio Config for gaming using VS Aptx Lite */
le_audio_client_audio_config_t  le_audio_client_audio_config_gaming_aptx_lite =
{
    .target_latency             = CAP_CLIENT_TARGET_LOWER_LATENCY,
    .sink_stream_capability     = CAP_CLIENT_STREAM_CAPABILITY_APTX_LITE_48_1,
    .source_stream_capability   = CAP_CLIENT_STREAM_CAPABILITY_UNKNOWN,
    .framing                    = LE_AUDIO_CLIENT_UNFRAMED,
    .phy_ctop                   = LE_AUDIO_CLIENT_Q2Q_PHY,
    .phy_ptoc                   = LE_AUDIO_CLIENT_Q2Q_PHY,
    .rtn_ctop                   = LE_AUDIO_CLIENT_APTX_LITE_RTN_GAME_NO_VBC_C_TO_P,
    .rtn_ptoc                   = 0x0
};

/*! Audio Config for gaming with VBC using VS Aptx Lite */
le_audio_client_audio_config_t  le_audio_client_audio_config_gaming_with_vbc_aptx_lite =
{
    .target_latency             = CAP_CLIENT_TARGET_LOWER_LATENCY,
    .sink_stream_capability     = CAP_CLIENT_STREAM_CAPABILITY_APTX_LITE_48_1,
    .source_stream_capability   = CAP_CLIENT_STREAM_CAPABILITY_APTX_LITE_16_1 ,
    .framing                    = LE_AUDIO_CLIENT_UNFRAMED,
    .phy_ctop                   = LE_AUDIO_CLIENT_Q2Q_PHY,
    .phy_ptoc                   = LE_AUDIO_CLIENT_Q2Q_PHY,
    .rtn_ctop                   = LE_AUDIO_CLIENT_APTX_LITE_RTN_GAME_WITH_VBC_C_TO_P,
    .rtn_ptoc                   = LE_AUDIO_CLIENT_APTX_LITE_RTN_GAME_WITH_VBC_P_TO_C
};

#endif /* INCLUDE_LE_AUDIO_GAMING_MODE_APTX_LITE */

const le_audio_client_audio_config_t* leAudioClient_GetAudioConfig(CapClientContext audio_context, uint8 codec)
{
    le_audio_client_audio_config_t *audio_configuration = NULL;

#ifndef INCLUDE_LE_AUDIO_GAMING_MODE_APTX_LITE
    UNUSED(codec);
#endif

    switch (audio_context)
    {
        case CAP_CLIENT_CONTEXT_TYPE_GAME:
#ifdef INCLUDE_LE_AUDIO_GAMING_MODE_APTX_LITE
            audio_configuration = codec == KYMERA_LE_AUDIO_CODEC_APTX_LITE ? &le_audio_client_audio_config_gaming_aptx_lite : &le_audio_client_audio_config_gaming;
#else
            audio_configuration = &le_audio_client_audio_config_gaming;
#endif
        break;

        case CAP_CLIENT_CONTEXT_TYPE_GAME_WITH_VBC:
#ifdef INCLUDE_LE_AUDIO_GAMING_MODE_APTX_LITE
            audio_configuration = codec == KYMERA_LE_AUDIO_CODEC_APTX_LITE ? &le_audio_client_audio_config_gaming_with_vbc_aptx_lite : &le_audio_client_audio_config_gaming_with_vbc;
#else
            audio_configuration = &le_audio_client_audio_config_gaming_with_vbc;
#endif
        break;

        case CAP_CLIENT_CONTEXT_TYPE_MEDIA:
            audio_configuration = &le_audio_client_audio_config_media;
        break;

        case CAP_CLIENT_CONTEXT_TYPE_CONVERSATIONAL:
            audio_configuration = &le_audio_client_audio_config_conversational;
        break;

        default:
        break;
    }

    return audio_configuration;
}

#endif /* INCLUDE_LE_AUDIO_UNICAST_SOURCE */

void leAudioClient_AudioConfigInit(void)
{
#ifdef INCLUDE_LE_AUDIO_BROADCAST_SOURCE
    lea_client_bcast_config.sub_group_info =
            (TmapClientBigSubGroup*) PanicUnlessMalloc(sizeof(TmapClientBigSubGroup) +
                                                       (TMAP_BROADCAST_MAX_SUPPORTED_BIS *
                                                        sizeof(TmapClientBisInfo)));
#endif
}

#ifdef INCLUDE_LE_AUDIO_BROADCAST_SOURCE

void leAudioClient_SetBroadcastAudioConfigType(le_audio_client_broadcast_config_type_t config_type)
{
    lea_client_bcast_config.config_type = config_type;
}

const le_audio_client_audio_broadcast_config_t* leAudioClient_GetBroadcastAudioConfig(void)
{
    le_audio_client_audio_broadcast_config_t *audio_configuration = NULL;

    switch (lea_client_bcast_config.config_type)
    {
        case LE_AUDIO_CLIENT_BROADCAST_CONFIG_TYPE_HQ:
        {
            audio_configuration = &lea_client_bcast_config;
            audio_configuration->num_sub_group = LE_AUDIO_CLIENT_BROADCAST_NUM_SUB_GROUPS;
            audio_configuration->presentation_delay = LE_AUDIO_CLIENT_BROADCAST_PRESENTATION_DELAY;
            audio_configuration->sub_group_info->config = TMAP_CLIENT_STREAM_CAPABILITY_48_2;
            audio_configuration->sub_group_info->targetLatency = CAP_CLIENT_TARGET_BALANCE_LATENCY_AND_RELIABILITY;
            audio_configuration->sub_group_info->lc3BlocksPerSdu = LE_AUDIO_CLIENT_BROADCAST_LC3_BLOCKS_PER_SDU;
            audio_configuration->sub_group_info->useCase = TMAP_CLIENT_CONTEXT_TYPE_MEDIA;
            audio_configuration->sub_group_info->metadataLen = 0;
            audio_configuration->sub_group_info->metadata = NULL;
            audio_configuration->sub_group_info->numBis = LE_AUDIO_CLIENT_BROADCAST_HIGH_QUALITY_NUM_BIS;

            audio_configuration->sub_group_info->bisInfo[0].config = TMAP_CLIENT_STREAM_CAPABILITY_48_2;
            audio_configuration->sub_group_info->bisInfo[1].config = TMAP_CLIENT_STREAM_CAPABILITY_48_2;
            audio_configuration->sub_group_info->bisInfo[0].audioLocation = BAP_AUDIO_LOCATION_FL;
            audio_configuration->sub_group_info->bisInfo[1].audioLocation = BAP_AUDIO_LOCATION_FR;
            audio_configuration->sub_group_info->bisInfo[0].targetLatency = CAP_CLIENT_TARGET_HIGH_RELIABILITY;
            audio_configuration->sub_group_info->bisInfo[1].targetLatency = CAP_CLIENT_TARGET_HIGH_RELIABILITY;
            audio_configuration->sub_group_info->bisInfo[0].lc3BlocksPerSdu = LE_AUDIO_CLIENT_BROADCAST_LC3_BLOCKS_PER_SDU;
            audio_configuration->sub_group_info->bisInfo[1].lc3BlocksPerSdu = LE_AUDIO_CLIENT_BROADCAST_LC3_BLOCKS_PER_SDU;
        }
        break;

        default:
        {
            Panic();
        }
        break;
    }

    return audio_configuration;
}

#endif /* INCLUDE_LE_AUDIO_BROADCAST_SOURCE */
